/**
 * @file debugger.cpp
 * @brief VimL虚拟机调试器实现
 * @author VimLVM Team
 * @date 2025
 */

#include "viml/debugger.h"
#include "viml/vm.h"
#include <algorithm>

namespace viml {

// Debugger实现
Debugger::Debugger(VM& vm) : vm_(vm), debugging_(false), step_mode_(StepMode::NONE) {}

void Debugger::start_debugging() {
    debugging_ = true;
}

void Debugger::stop_debugging() {
    debugging_ = false;
    clear_breakpoints();
}

void Debugger::add_breakpoint(const std::string& filename, size_t line) {
    breakpoints_[filename].insert(line);
}

void Debugger::remove_breakpoint(const std::string& filename, size_t line) {
    auto it = breakpoints_.find(filename);
    if (it != breakpoints_.end()) {
        it->second.erase(line);
        if (it->second.empty()) {
            breakpoints_.erase(it);
        }
    }
}

void Debugger::clear_breakpoints() {
    breakpoints_.clear();
}

std::vector<std::pair<std::string, size_t>> Debugger::list_breakpoints() const {
    std::vector<std::pair<std::string, size_t>> result;
    for (const auto& [filename, lines] : breakpoints_) {
        for (size_t line : lines) {
            result.emplace_back(filename, line);
        }
    }
    return result;
}

void Debugger::step_into() {
    step_mode_ = StepMode::INTO;
    step_target_frame_ = 0; // 不关心帧深度
    vm_.resume();
}

void Debugger::step_over() {
    step_mode_ = StepMode::OVER;
    step_target_frame_ = vm_.call_stack().size();
    vm_.resume();
}

void Debugger::step_out() {
    step_mode_ = StepMode::OUT;
    auto stack = vm_.call_stack();
    if (stack.size() > 1) {
        step_target_frame_ = stack.size() - 1;
    } else {
        step_target_frame_ = 0;
    }
    vm_.resume();
}

void Debugger::continue_execution() {
    step_mode_ = StepMode::NONE;
    vm_.resume();
}

Value Debugger::get_variable(const std::string& name) const {
    // 先查找局部变量
    Value local = vm_.get_local(name);
    if (!local.is_nil()) {
        return local;
    }
    
    // 再查找全局变量
    return vm_.get_global(name);
}

std::unordered_map<std::string, Value> Debugger::get_local_variables() const {
    std::unordered_map<std::string, Value> locals;
    auto stack = vm_.call_stack();
    if (!stack.empty()) {
        return stack.back().locals;
    }
    return locals;
}

std::unordered_map<std::string, Value> Debugger::get_global_variables() const {
    return vm_.get_all_globals();
}

std::vector<VM::StackFrame> Debugger::get_call_stack() const {
    return vm_.call_stack();
}

size_t Debugger::get_current_line() const {
    return vm_.current_line();
}

std::string Debugger::get_current_function() const {
    return vm_.current_function();
}

std::string Debugger::get_current_file() const {
    auto stack = vm_.call_stack();
    if (!stack.empty()) {
        return stack.back().function_name; // 简化为函数名
    }
    return "";
}

void Debugger::set_event_handler(std::unique_ptr<DebugEventHandler> handler) {
    handler_ = std::move(handler);
}

void Debugger::load_debug_info(const std::string& filename, std::shared_ptr<DebugInfo> info) {
    debug_info_[filename] = std::move(info);
}

bool Debugger::should_break_at(const std::string& filename, size_t line) const {
    auto it = breakpoints_.find(filename);
    if (it != breakpoints_.end()) {
        return it->second.count(line) > 0;
    }
    return false;
}

void Debugger::handle_breakpoint(const std::string& filename, size_t line) {
    if (should_break_at(filename, line)) {
        notify_event(DebugEvent::BREAKPOINT_HIT, line);
    }
}

void Debugger::notify_event(DebugEvent event, size_t line, const std::string& message) {
    if (handler_) {
        handler_->on_event(event, line, message);
    }
}

} // namespace viml